package org.promote.hotspot.dashboard.launcher;

import io.etcd.jetcd.KeyValue;
import io.etcd.jetcd.Watch;
import io.etcd.jetcd.watch.WatchEvent;
import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.promote.hotspot.common.config.ConfigConstant;
import org.promote.hotspot.common.etcd.JetcdClient;
import org.promote.hotspot.common.rule.KeyRule;
import org.promote.hotspot.common.tool.FastJsonUtils;
import org.promote.hotspot.common.tool.IpUtils;
import org.promote.hotspot.dashboard.util.RuleUtil;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * 启动和初始化etcd先关的组件
 *
 * @author enping.jep
 * @date 2024/03/18 11:19
 **/
@Component
@Slf4j
public class EtcdLauncher {

    @Resource
    private JetcdClient client;

    @PostConstruct
    private void launch() {
        ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        //定时上传dashboard的地址信息
        scheduledExecutorService.scheduleAtFixedRate(this::uploadSelfInfo, 3, 30, TimeUnit.SECONDS);

        fetchRuleFromEtcd();//获取规则列表


    }

    /**
     * 获取规则列表
     */
    private void fetchRuleFromEtcd() {
        RuleUtil.init();
        List<KeyValue> keyValues = client.getPrefix(ConfigConstant.RULE_PATH);
        for (KeyValue keyValue : keyValues) {
            log.info(keyValue.getKey() + "---" + keyValue.getValue());
            String appName = keyValue.getKey().toString(StandardCharsets.UTF_8).replace(ConfigConstant.RULE_PATH, "");
            //如果appName为空，则删除对应的规则
            if (StringUtils.isEmpty(appName)) {
                client.delete(keyValue.getKey());
                continue;
            }
            String rulesStr = keyValue.getValue().toString(StandardCharsets.UTF_8);
            RuleUtil.put(appName, FastJsonUtils.toList(rulesStr, KeyRule.class));
        }
    }

    /**
     * 观察规则变化
     */
    private void watchRule() {
        String key = ConfigConstant.RULE_PATH;
        log.info(getClass() + "--- begin watch rule change ----");
        client.watch(key, Watch.listener(watchResponse -> {
            log.info("收到[{}]的事件", key);
            // 如果发生了变化
            if (!watchResponse.getEvents().isEmpty()) {
                fetchRuleFromEtcd();
            }
        }));
    }

    /**
     * 每隔30秒上传一下自己的地址信息
     */
    private void uploadSelfInfo() {
        client.putWithLease(ConfigConstant.DASH_BOARD_PATH + IpUtils.getHostName(),
                IpUtils.getIp() + ":" + ConfigConstant.DASH_BOARD_PORT, 30);
    }
}
